/*
* org.openmicroscopy.shoola.util.ui.treetable.TreeTable
*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2007 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.util.ui.treetable;
//Java imports
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.swing.DefaultCellEditor;
import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.table.TableCellRenderer;
import javax.swing.tree.TreePath;
//Third-party libraries
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import org.jdesktop.swingx.table.ColumnHeaderRenderer;
import org.jdesktop.swingx.treetable.MutableTreeTableNode;
import org.jdesktop.swingx.treetable.TreeTableModel;
//Application-internal dependencies
import org.openmicroscopy.shoola.util.ui.UIUtilities;
import org.openmicroscopy.shoola.util.ui.treetable.editors.BooleanCellEditor;
import org.openmicroscopy.shoola.util.ui.treetable.editors.NumberCellEditor;
import org.openmicroscopy.shoola.util.ui.treetable.editors.StringCellEditor;
import org.openmicroscopy.shoola.util.ui.treetable.model.OMETreeNode;
import org.openmicroscopy.shoola.util.ui.treetable.renderers.BooleanCellRenderer;
import org.openmicroscopy.shoola.util.ui.treetable.renderers.IconCellRenderer;
import org.openmicroscopy.shoola.util.ui.treetable.renderers.NumberCellRenderer;
import org.openmicroscopy.shoola.util.ui.treetable.renderers.SelectionHighLighter;
/**
* A customized {@link JXTreeTable}.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author Donald MacDonald
* <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
* @version 3.0
* <small>
* (<b>Internal version:</b> $Revision: $Date: $)
* </small>
* @since OME3.0
*/
public class OMETreeTable
extends JXTreeTable
{
/** A map of the default cell editors in the table. */
protected static final Map<Class<?>, DefaultCellEditor> DEFAULT_EDITORS;
/** A map of the default cell renderers in the table. */
protected static final Map<Class<?>, TableCellRenderer> DEFAULT_RENDERERS;
static
{
DEFAULT_RENDERERS = new HashMap<Class<?>, TableCellRenderer>();
DEFAULT_RENDERERS.put(Boolean.class, new BooleanCellRenderer());
DEFAULT_RENDERERS.put(Long.class, new NumberCellRenderer());
DEFAULT_RENDERERS.put(Integer.class, new NumberCellRenderer());
DEFAULT_RENDERERS.put(Float.class, new NumberCellRenderer());
DEFAULT_RENDERERS.put(Double.class, new NumberCellRenderer());
DEFAULT_RENDERERS.put(String.class,
new NumberCellRenderer(SwingConstants.LEFT));
DEFAULT_RENDERERS.put(Icon.class, new IconCellRenderer());
// defaultTableRenderers.put(Color.class, new ColourCellRenderer());
DEFAULT_EDITORS = new HashMap<Class<?>, DefaultCellEditor>();
DEFAULT_EDITORS.put(Boolean.class,
// new BooleanCellEditor(new JCheckBox()));
new BooleanCellEditor((JCheckBox)
DEFAULT_RENDERERS.get(Boolean.class)));
DEFAULT_EDITORS.put(Integer.class,
new NumberCellEditor(new JTextField()));
DEFAULT_EDITORS.put(String.class,
new StringCellEditor(new JTextField()));
}
/** Tree expansion listener. */
protected TreeExpansionListener treeExpansionListener;
/** The mouse listener. */
//protected MouseListener mouseListener;
/** Initializes the table. */
private void initialize()
{
ColumnHeaderRenderer l =
(ColumnHeaderRenderer) getTableHeader().getDefaultRenderer();
l.setHorizontalAlignment(SwingConstants.CENTER);
}
/** Creates a new instance. */
public OMETreeTable()
{
super();
initialize();
}
/**
* Create an instance of the treetable.
*
* @param model The tree model.
*/
public OMETreeTable(TreeTableModel model)
{
super(model);
setTableModel(model);
initialize();
}
/**
* Sets the tree model.
*
* @param model The value to set.
*/
public void setTableModel(TreeTableModel model)
{
setTreeTableModel(model);
}
/** Sets the default high lighter for this table. */
protected void setDefaultHighLighter()
{
Highlighter h = HighlighterFactory.createAlternateStriping(
UIUtilities.BACKGROUND_COLOUR_EVEN,
UIUtilities.BACKGROUND_COLOUR_ODD);
addHighlighter(h);
addHighlighter(new SelectionHighLighter(this));
}
/**
* Return <code>true</code> if the left button was clicked,
* <code>false</code> otherwise.
*
* @param e The mouse event to handle.
* @return See above.
*/
protected boolean leftClick(MouseEvent e)
{
return (e.getButton() == MouseEvent.BUTTON1);
}
/**
* Sets the mouse listener for mouse events and attach it to the methods
* onLeftMouseDown(), onRightMouseDown()
*/
protected void setListeners()
{
MouseListener mouseListener = new MouseListener()
{
public void mouseClicked(MouseEvent e) { onMouseClicked(e); }
public void mouseEntered(MouseEvent e) { onMouseEnter(e); }
public void mouseExited(MouseEvent e) { onMouseExit(e); }
public void mousePressed(MouseEvent e) { onMousePressed(e); }
public void mouseReleased(MouseEvent e) { onMouseReleased(e); }
};
addMouseListener(mouseListener);
}
/**
* MouseEvent called from mouseListener.
* This Event responds to mouseClicked events.
*
* @param e The mouse event to handle.
*/
protected void onMouseClicked(MouseEvent e) {}
/**
* MouseEvent called from mouseListener.
* This Event responds to mouse released events.
*
* @param e The mouse event to handle.
*/
protected void onMouseReleased(MouseEvent e) {}
/**
* MouseEvent called from mouseListener.
* This Event responds to mouse pressed events.
*
* @param e The mouse event to handle.
*/
protected void onMousePressed(MouseEvent e) {}
/**
* MouseEvent called from mouseListener.
* This Event responds to mouse enter events.
*
* @param e The mouse event to handle.
*/
protected void onMouseEnter(MouseEvent e) {}
/**
* MouseEvent called from mouseListener.
* This Event responds to mouseExit events.
*
* @param e The mouse event to handle.
*/
protected void onMouseExit(MouseEvent e) {}
/**
* Sets the tree expansion listener for the tree.
* Attach the collapse and expand events to the onNodeNavigation
* method.
*/
protected void setTreeExpansionListener()
{
treeExpansionListener = new TreeExpansionListener()
{
public void treeCollapsed(TreeExpansionEvent e)
{
onNodeNavigation(e, false);
}
public void treeExpanded(TreeExpansionEvent e)
{
onNodeNavigation(e, true);
}
};
addTreeExpansionListener(treeExpansionListener);
}
/**
* This method is called when a node in the tree is expanded or
* collapsed.
*
* @param e The tree event.
* @param expanded Pass <code>true</code> if the node was expanded,
* <code>false</code> otherwise.
*/
protected void onNodeNavigation(TreeExpansionEvent e, boolean expanded)
{
OMETreeNode node = (OMETreeNode) e.getPath().getLastPathComponent();
node.setExpanded(expanded);
}
/**
* Sets the default editors for the cells in the table. This includes
* editors for cells containing: int, long, string, booleans,
* floats, longs, doubles.
*/
protected void setDefaultEditors()
{
Iterator<Class<?>> classIterator = DEFAULT_EDITORS.keySet().iterator();
Class<?> classType;
DefaultCellEditor editorType;
while(classIterator.hasNext()) {
classType = classIterator.next();
editorType = DEFAULT_EDITORS.get(classType);
this.setDefaultEditor(classType, editorType);
}
}
/**
* Sets the default renderers for the cells in the table. This includes
* renderers for cells containing: dates, int, long, string, booleans,
* floats, longs, doubles, colour.
*/
protected void setDefaultRenderers()
{
Iterator<Class<?>>
classIterator = DEFAULT_RENDERERS.keySet().iterator();
Class<?> classType;
TableCellRenderer rendererType;
while (classIterator.hasNext()) {
classType = classIterator.next();
rendererType = DEFAULT_RENDERERS.get(classType);
setDefaultRenderer(classType, rendererType);
}
}
/**
* Expands the row with the node in it.
*
* @param node The node to handle.
*/
public void expandNode(OMETreeNode node)
{
if (node != null) expandPath(node.getPath());
}
/**
* Collapses the row with the node in it.
*
* @param node The node to handle.
*/
public void collapseNode(OMETreeNode node)
{
if (node != null) collapsePath(node.getPath());
}
/**
* Overrides the {@link JXTreeTable#expandPath(TreePath)}
* Adds extra control to set the expanded flag in the OMETreeNode.
* @see JXTreeTable#expandPath(TreePath)
*/
public void expandPath(TreePath path)
{
super.expandPath(path);
if (path == null) return;
OMETreeNode node = (OMETreeNode) path.getLastPathComponent();
if (node != null) node.setExpanded(true);
}
/**
* Overrides the {@link JXTreeTable#expandRow(int)}
* Adds extra control to set the expanded flag in the OMETreeNode.
* @see JXTreeTable#expandRow(int)
*/
public void expandRow(int row)
{
super.expandRow(row);
OMETreeNode node = getNodeAtRow(row);
if (node != null) node.setExpanded(true);
}
/**
* Overrides the {@link JXTreeTable#expandAll()}
* Adds extra control to set the expanded flag in the OMETreeNode.
* @see JXTreeTable#expandAll()
*/
public void expandAll()
{
super.expandAll();
MutableTreeTableNode root =
(MutableTreeTableNode) getTreeTableModel().getRoot();
if (root == null) return;
for (MutableTreeTableNode node : ((OMETreeNode) root).getChildList())
((OMETreeNode) node).setExpanded(true);
}
/**
* Helper method to get the node at row.
*
* @param row The selected row.
* @return See above.
*/
public OMETreeNode getNodeAtRow(int row)
{
TreePath path = getPathForRow(row);
if (path == null) return null;
return (OMETreeNode) path.getLastPathComponent();
}
/**
* Gets the row a node is at.
*
* @param node The node.
* @return See above.
*/
public int getRow(OMETreeNode node)
{
if (node == null) return -1;
return getRowForPath(node.getPath());
}
/**
* Returns <code>true</code> if the cell editable for this node and column,
* <code>false</code> otherwise.
*
* @param node The node of the tree.
* @param column The field to edit.
* @return See above.
*/
public boolean isCellEditable(Object node, int column)
{
return getTreeTableModel().isCellEditable(node, column);
}
/**
* Selects a node.
*
* @param node The node to select.
*/
public void selectNode(OMETreeNode node)
{
int row = getRow(node);
selectionModel.addSelectionInterval(row, row);
}
/**
* Overrides the {@link JXTreeTable#collapsePath(TreePath)}
* Adds extra control to set the expanded flag in the OMETreeNode.
* @see JXTreeTable#collapsePath(TreePath)
*/
public void collapsePath(TreePath path)
{
super.collapsePath(path);
if (path == null) return;
OMETreeNode node = (OMETreeNode) path.getLastPathComponent();
if (node != null) node.setExpanded(false);
}
/**
* Overrides the {@link JXTreeTable#collapseRow(int)}
* Adds extra control to set the expanded flag in the OMETreeNode.
* @see JXTreeTable#collapseRow(int)
*/
public void collapseRow(int row)
{
super.collapseRow(row);
OMETreeNode node = getNodeAtRow(row);
if (node != null) node.setExpanded(false);
}
/**
* Overrides the {@link JXTreeTable#collapseAll()}
* Adds extra control to set the expanded flag in the OMETreeNode.
* @see JXTreeTable#collapseAll()
*/
public void collapseAll()
{
super.collapseAll();
MutableTreeTableNode root =
(MutableTreeTableNode) getTreeTableModel().getRoot();
if (root == null) return;
for (MutableTreeTableNode node : ((OMETreeNode) root).getChildList())
((OMETreeNode) node).setExpanded(true);
}
/**
* Overridden to set the various renderer.
* @see JXTreeTable#setTreeTableModel(TreeTableModel)
*/
public void setTreeTableModel(TreeTableModel model)
{
super.setTreeTableModel(model);
setColumnSelectionAllowed(false);
setRowSelectionAllowed(true);
setCellSelectionEnabled(false);
setTreeExpansionListener();
setListeners();
setDefaultRenderers();
setDefaultEditors();
setDefaultHighLighter();
}
}